1 Data Preparation

To create the data set used for this analysis, four data sets were imported and manipulated. One dataset included income, one life expectancy, one population size, and a final dataset with region. All data sets were combined in order to create a final data set with the following variables:

  • Country
  • Income
  • Year
  • Life Expectancy
  • Region
  • Population Size

This final data set will be evaluated in the following sections. Please refer to the following code that was used in order to create this dataset.

income <- read.csv(file="https://isarenn.github.io/irennenberg/Week5/income_per_person.csv")
life <- read.csv(file="https://isarenn.github.io/irennenberg/Week5/life_expectancy_years.csv")
population <- read.csv(file="https://isarenn.github.io/irennenberg/Week5/population_total.csv")
region <- read.csv((file="https://isarenn.github.io/irennenberg/Week5/countries_total.csv"))

##reading in files from github

##reshape income so that there are three columns, country year and income

income2 <- income %>%
  gather(key="Year",
         value="Income",
         - geo,
         na.rm=TRUE)
income3 <- income2 %>%
  mutate(Year=substr(Year,2,5))

names(income3)[1]='Country'

##reshape life expectancy : country, year, life expectancy

life2 <- life %>%
  gather(key="Year",
         value="LifeExp",
         - geo,
         na.rm=TRUE)
life3 <- life2 %>%
  mutate(Year=substr(Year,2,5))

names(life3)[1]='Country'

##reshaping population in the same way. 

pop2 <- population %>%
  gather(key="Year",
         value="Population",
         - geo,
         na.rm=TRUE)
pop3 <- pop2 %>%
  mutate(Year=substr(Year,2,5))

names(pop3)[1]='Country'

##Merge/join the above life and income sets to create one new dataset 'LifeExpIncom' with variables country,year,lifeexp and income

LifeExpIncom <- merge(income3, life3, by=c("Year","Country"))

## Merge the above dataset with the region dataset, so that the resulting dataset has income, lifeexp, population size and country region

names(region)[1]='Country'
region2 <- subset(region, select=-c(alpha.2, alpha.3, country.code, iso_3166.2, sub.region, intermediate.region, region.code, sub.region.code, intermediate.region.code))

LifeExpIncom2 <- merge(LifeExpIncom, region2, by="Country")

##Merge the above dataset with population so that there is income, lifeexp, population size country region and population size

LifeExpIncom3 <- merge(LifeExpIncom2, pop3, by=c("Year","Country"))

write.csv(LifeExpIncom3, "LifeExpIncomFinal.csv")

2 Data Set Description

The final data set has 37,590 observations and 6 variables. The data sets were retrieved from the course project data repository under the World Life Expectancy data section. The data was collected from a public domain.

3 Data For Year 2000 and 2015

In order to proceed with the data set, two datasets were created from the following years: 2000 and 2015. The data was subset using the below code.

d2000data <- LifeExpIncom3 %>%
  filter(Year=='2000')

d2015data <- LifeExpIncom3 %>%
  filter(Year=='2015')

4 Usage of ggplot Scatterplot

A scatter plot of Income and Life Expectancy was created for the year 2000.

The below data plot shows that life expectancy is very low the close the income gets to zero. As income increases, as does life expectancy. Life expectancy increases very sharply from 0 to ~1500, where afterwards it stabilizes as income increases.

d2000.income <- d2000data$Income
d2000.lifeexp <- d2000data$LifeExp
d2000.country <- d2000data$Country
d2000.region <- d2000data$region
d2000.pop <- d2000data$Population

ggplot(data = d2000data, mapping = aes(x = d2000.income, y = d2000.lifeexp)) +
  geom_point()+
  labs(
                 x = "Income",
                 y = "Life Expectancy",
                 title = "Association between Income and Life Expectancy",
                 subtitle = "Data for the Year 2000",
                 caption = paste("Created on", Sys.Date())) +
             theme_gray() 

5 Manipulating the ggplot to Include the Third Numeric Variable

Now, the point size will be manipulated to display the population size for the same year.

This dataset now shows bigger points as being higher populations. It is seen that higher populations tend to be lower on the spectrum in terms of income. The very high income areas show points that have a smaller size, and therefore smaller population.

ggplot(data = d2000data, mapping = aes(x = d2000.income, y = d2000.lifeexp, size=d2000.pop)) +
  geom_point()+
  labs(
                 x = "Income",
                 y = "Life Expectancy",
                 size="Population Size",
                 title = "Association between Income and Life Expectancy",
                 subtitle = "Data for the Year 2000",
                 caption = paste("Created on", Sys.Date())) +
             theme_gray() 

6 Manipulating the ggplot to Include the Categorical Region Variable

Now, the point color will be manipulated to show the 5 different region categories for the same year. The categories are as follows:

  • Africa
  • Americas
  • Asia
  • Europe
  • Oceania

This final scatter plot shows us some distinct sections for select regions. The lower region, or Africa, tends to be localized near the lower life expectancy and lower income. The Asia region spans the largest income range, from being localized above the Africa cluster, to all the way to the right (or the highest income group). Within the Asia group, Oceania, Americas and Europe reside. Not all regions are isolated to one area of the scatter plot. There are certain trends for areas in which the regions reside, but there are some points that exceed that area. For example, there are a few Africa region points that are among the Americas/Europe/Asia points.

It is important to note that the frequency for the Oceania region is much lower than the other regions.

ggplot(data = d2000data, mapping = aes(x = d2000.income, y = d2000.lifeexp, size=d2000.pop, color=d2000.region)) +
  geom_point()+
  scale_color_manual(values=c("#FFD700", "#EA5F94","#0000FF","#84FFA9","#FF8F00")) +
  labs(
                 x = "Income",
                 y = "Life Expectancy",
                 size="Population Size",
                 color="Region",
                 title = "Association between Income and Life Expectancy",
                 subtitle = "Data for the Year 2000",
                 caption = paste("Created on", Sys.Date())) +
             theme_gray() 

7 Interactive Plot for Year 2015

An interactive plot was created for the 2015 dataset. The interactive scatter plot was made to display the association between life expectancy and income.

Since population size was so large, it was sized by dividing the population by: **~(2*log(data.pop)-11)^2.** .

d2015.income <- d2015data$Income
d2015.lifeexp <- d2015data$LifeExp
d2015.country <- d2015data$Country
d2015.region <- d2015data$region
d2015.pop <- d2015data$Population
d2015.pop2 <- d2015.pop/10000000
pal <- c("#ffbe0b", "#fb5607", "#ff006e","#8338ec","#3a86ff")

plot_ly(
    data = d2015data,
    x = ~d2015.income,  # Horizontal axis 
    y = ~d2015.lifeexp,   # Vertical axis 
    color = ~factor(d2015.region),  # must be a numeric factor
    colors=pal,
    text = ~paste("Population Size: ", d2015.pop,
                   "<br>Region:", d2015.region,
                   "<br>Country:", d2015.country), 
     # Show the species in the hover text
     ## using the following hovertemplate() to add the information of the
     ## Two numerical variables to the hover text.
     ### Use the following hover template to display more information
     hovertemplate = paste('<i><b>Life Expectancy<b></i>: %{y}',
                           '<br><b>Income</b>:  %{x}',
                           '<br><b>%{text}</b>'),
     alpha  = 0.6,
     marker = list(size = ~~(2*log(d2015.pop)-11)^2, sizeref = .05, sizemode = 'area' ),
     type = "scatter",
     mode = "markers",
     size.mode='area',
     ## graphic size
     width = 700,
     height = 350
   ) %>%
    layout(  
      ### Title 
      title =list(text = "Income vs Life Expectancy for the Year 2015", 
                  font = list(family = "Times New Roman",  # HTML font family  
                                size = 18,
                               color = "#ff006e")), 
      ### legend
      legend = list(title = list(text = 'Region',
                                 font = list(family = "Times New Roman",
                                               size = 14,
                                              color = "black")),
                    bgcolor = "#f7f7f7",
                    bordercolor = "black",
                    groupclick = "togglegroup",  # one of  "toggleitem" AND "togglegroup".
                    orientation = "v"  # Sets the orientation of the legend.
                    ),
      ## Backgrounds
      plot_bgcolor ='#f7f7f7', 
      ## Axes labels
             xaxis = list( 
                    title=list(text = 'Income',
                               font = list(family = 'Times New Roman')),
                    zerolinecolor = 'gray', 
                    zerolinewidth = 2, 
                    gridcolor = 'white'), 
            yaxis = list( 
                    title=list(text = 'Life Expectancy',
                               font = list(family = 'Times New Roman')),
                    zerolinecolor = 'purple', 
                    zerolinewidth = 2, 
                    gridcolor = 'white'),
       ## annotations
       annotations = list(  
                     x = 0.7,   # between 0 and 1. 0 = left, 1 = right
                     y = 1.5,   # between 0 and 1, 0 = bottom, 1 = top
                  font = list(size = 12,
                              color = "#ff006e"),   
                  text = "The point size is proportional to population size.",   
                  xref = "paper",  # "container" spans the entire `width` of the 
                                   #  lot. "paper" refers to the width of the 
                                   #  plotting area only. yref = "paper",  
                                   #  same as xref.
               xanchor = "center", #  horizontal alignment with respect to its x position
               yanchor = "bottom", #  similar to xanchor  
             showarrow = FALSE)
    )

8 Animated Plot

This animated plot aids in looking at the trends over time for the association between income and life expectancy for the entirety of the dataset.

data.income <- LifeExpIncom3$Income
data.lifeexp <- LifeExpIncom3$LifeExp
data.country <- LifeExpIncom3$Country
data.region <- LifeExpIncom3$region
data.pop <- LifeExpIncom3$Population
data.year <- LifeExpIncom3$Year
pal.IBM <- c("#ffbe0b", "#fb5607", "#ff006e","#8338ec","#3a86ff")
pal.IBM <- setNames(pal.IBM, c("Asia", "Europe", "Africa", "Americas", "Oceania"))

df <- LifeExpIncom3 
fig <- df %>%
  plot_ly(
    x = ~data.income, 
    y = ~data.lifeexp, 
    size = ~(2*log(data.pop)-11)^2,
    color = ~data.region, 
    colors = pal.IBM,   # custom colors
    #marker = list(size = ~(log(pop)-10),  sizemode = 'area'),
    frame = ~data.year,      # the time variable to
    # to display in the hover
    text = ~paste("Country:", data.country,
                  "<br>Continent:", data.region,
                  "<br>Year:", data.year,
                  "<br>Income:", data.income,
                  "<br>LifeExp:", data.lifeexp,
                  "<br>Population:", data.pop),
    hoverinfo = "text",
    type = 'scatter',
    mode = 'markers'
  ) %>%
  layout(
    title=list(text="Income vs Life Expectancy from 1800-2018",
               font=list(family="Time New Roman",
                         size=18,
                         color="#ff006e")),
    xaxis = list( 
                    title=list(text = 'Income',
                               font = list(family = 'Times New Roman')),
                    gridcolor = 'white'), 
            yaxis = list( 
                    title=list(text = 'Life Expectnacy',
                               font = list(family = 'Times New Roman')),
                    gridcolor = 'white')
  )
fig <- fig %>% layout(
    xaxis = list(
      type = "log"
    )
  )

fig

9 Final Conlusions

The original data sets were manipulated to create one large dataset with the following variables: country, income, year, life expectancy, region and population size.

As seen with the animated scatter plot (previous section), income and life expectancy increased over time from the years 1800-2018 (the entire span of the data sets). There were several instances in which there were drastic drops in the life expectancy, around the time of World Wars. There is a relationship throughout time between life expectancy and income.

For the three graphs created with the data from 2000, it is evident that there is a relationship between income and life expectancy. Points of high income and life expectancy were all smaller in size, indicating a lower population, with the exception of a point for the Americas in the final graph. It was found that when changing the color for region, it was most evident that the Africa region was densely close at the lower income and lower life expectancy area. The other four regions- Oceania, Europe, Asia and Americas, were (for the most part) higher than the Africa region for life expectancy and income. There were some Africa points on the graph that were among the other regions. The Asia region was second to Africa in that there seemed to be grouping of points in the mid-range of the graph.

The graph showed that from the 0 to ~1500 income range, there was a sharp increase in life expectancy. Following ~30,000 (income) the life expectancy remains stable. Life expectancy was the lowest when income was incredibly close to 0, and increased exponentially the farther away from zero until the stabilization occurred.

For the interactive plot from the year 2015, there are similar relationships in the graph. Notably, the point with the highest income comes from Qatar, and the lowest income (and life expectancy) comes from the Central African Republic. Similarly to the 2000 year scatter plot, there is a sharp increase earlier in the plot, and then a leveling out, around 20,000.

Thank you and good night!

LS0tDQp0aXRsZTogIkNvdW50cnkgQ29tcGFyaXNvbnMiDQphdXRob3I6ICJJc2FiZWxsZSBSZW5uZW5iZXJnIg0Kb3V0cHV0OiANCiAgaHRtbF9kb2N1bWVudDogDQogICAgY29kZV9mb2xkaW5nOiBoaWRlDQogICAgdG9jOiB0cnVlDQogICAgdG9jX2Zsb2F0OiB0cnVlDQogICAgdG9jX2NvbGxhcHNlZDogdHJ1ZQ0KICAgIHRvY19kZXB0aDogNA0KICAgIHRoZW1lOiAic3BhY2VsYWIiDQogICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlDQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQ0KICAgICAgDQogICAgDQotLS0gIA0KDQo8c3R5bGUgdHlwZT0idGV4dC9jc3MiPg0KDQpoMS50aXRsZSB7DQogIGZvbnQtc2l6ZTogMzhweDsNCiAgY29sb3I6ICMwMDAwRkY7DQogIHRleHQtYWxpZ246IGNlbnRlcjsNCn0NCmg0LmF1dGhvciB7IC8qIEhlYWRlciA0IC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovDQogICAgZm9udC1zaXplOiAxOHB4Ow0KICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsNCiAgY29sb3I6ICM0MWI2YzQ7DQogIHRleHQtYWxpZ246IGNlbnRlcjsNCn0NCmgxIHsNCiAgICBmb250LXNpemU6IDIycHg7DQogICAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7DQogICAgY29sb3I6ICM0MWI2YzQ7DQogICAgdGV4dC1hbGlnbjogbGVmdDsNCn0NCjwvc3R5bGU+DQoNCg0KYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9DQpvcHRpb25zKHJlcG9zID0gbGlzdChDUkFOPSJodHRwOi8vY3Jhbi5yc3R1ZGlvLmNvbS8iKSkNCmlmICghcmVxdWlyZSgidGlkeXZlcnNlIikpIHsNCiAgIGluc3RhbGwucGFja2FnZXMoInRpZHl2ZXJzZSIpDQogICBsaWJyYXJ5KHRpZHl2ZXJzZSkNCn0NCmlmICghcmVxdWlyZSgia25pdHIiKSkgew0KICAgaW5zdGFsbC5wYWNrYWdlcygia25pdHIiKQ0KICAgbGlicmFyeShrbml0cikNCn0NCmlmICghcmVxdWlyZSgiY293cGxvdCIpKSB7DQogICBpbnN0YWxsLnBhY2thZ2VzKCJjb3dwbG90IikNCiAgIGxpYnJhcnkoY293cGxvdCkNCn0NCmlmICghcmVxdWlyZSgibGF0ZXgyZXhwIikpIHsNCiAgIGluc3RhbGwucGFja2FnZXMoImxhdGV4MmV4cCIpDQogICBsaWJyYXJ5KGxhdGV4MmV4cCkNCn0NCmlmICghcmVxdWlyZSgicGxvdGx5IikpIHsNCiAgIGluc3RhbGwucGFja2FnZXMoInBsb3RseSIpDQogICBsaWJyYXJ5KHBsb3RseSkNCn0NCmlmICghcmVxdWlyZSgiZ2FwbWluZGVyIikpIHsNCiAgIGluc3RhbGwucGFja2FnZXMoImdhcG1pbmRlciIpDQogICBsaWJyYXJ5KGdhcG1pbmRlcikNCn0NCmlmICghcmVxdWlyZSgicG5nIikpIHsNCiAgICBpbnN0YWxsLnBhY2thZ2VzKCJwbmciKSAgICANCiAgICBsaWJyYXJ5KCJwbmciKQ0KfQ0KaWYgKCFyZXF1aXJlKCJSQ3VybCIpKSB7DQogICAgaW5zdGFsbC5wYWNrYWdlcygiUkN1cmwiKSAgICANCiAgICBsaWJyYXJ5KCJSQ3VybCIpDQp9DQppZiAoIXJlcXVpcmUoImNvbG91cnBpY2tlciIpKSB7DQogICAgaW5zdGFsbC5wYWNrYWdlcygiY29sb3VycGlja2VyIikgICAgICAgICAgICAgIA0KICAgIGxpYnJhcnkoImNvbG91cnBpY2tlciIpDQp9DQppZiAoIXJlcXVpcmUoImdnYW5pbWF0ZSIpKSB7DQogICAgaW5zdGFsbC5wYWNrYWdlcygiZ2dhbmltYXRlIikgICAgICAgICAgICAgIA0KICAgIGxpYnJhcnkoImdnYW5pbWF0ZSIpDQp9DQppZiAoIXJlcXVpcmUoImdpZnNraSIpKSB7DQogICAgaW5zdGFsbC5wYWNrYWdlcygiZ2lmc2tpIikgICAgICAgICAgICAgIA0KICAgIGxpYnJhcnkoImdpZnNraSIpDQp9DQppZiAoIXJlcXVpcmUoIm1hZ2ljayIpKSB7DQogICAgaW5zdGFsbC5wYWNrYWdlcygibWFnaWNrIikgICAgICAgICAgICAgIA0KICAgIGxpYnJhcnkoIm1hZ2ljayIpDQp9DQppZiAoIXJlcXVpcmUoImdyRGV2aWNlcyIpKSB7DQogICAgaW5zdGFsbC5wYWNrYWdlcygiZ3JEZXZpY2VzIikgICAgICAgICAgICAgIA0KICAgIGxpYnJhcnkoImdyRGV2aWNlcyIpDQp9DQppZiAoIXJlcXVpcmUoImpwZWciKSkgew0KICAgIGluc3RhbGwucGFja2FnZXMoImpwZWciKSAgICAgICAgICAgICAgDQogICAgbGlicmFyeSgianBlZyIpDQp9DQppZiAoIXJlcXVpcmUoImdncmlkZ2VzIikpIHsNCiAgICBpbnN0YWxsLnBhY2thZ2VzKCJnZ3JpZGdlcyIpICAgICAgICAgICAgICANCiAgICBsaWJyYXJ5KCJnZ3JpZGdlcyIpDQp9DQppZiAoIXJlcXVpcmUoInBseXIiKSkgew0KICAgIGluc3RhbGwucGFja2FnZXMoInBseXIiKSAgICAgICAgICAgICAgDQogICAgbGlicmFyeSgicGx5ciIpDQp9DQppZiAoIXJlcXVpcmUoImdnaXJhcGgiKSkgew0KICAgIGluc3RhbGwucGFja2FnZXMoImdnaXJhcGgiKSAgICAgICAgICAgICAgDQogICAgbGlicmFyeSgiZ2dpcmFwaCIpDQp9DQppZiAoIXJlcXVpcmUoImhpZ2hjaGFydGVyIikpIHsNCiAgICBpbnN0YWxsLnBhY2thZ2VzKCJoaWdoY2hhcnRlciIpICAgICAgICAgICAgICANCiAgICBsaWJyYXJ5KCJoaWdoY2hhcnRlciIpDQp9DQppZiAoIXJlcXVpcmUoImZvcmVjYXN0IikpIHsNCiAgICBpbnN0YWxsLnBhY2thZ2VzKCJmb3JlY2FzdCIpICAgICAgICAgICAgICANCiAgICBsaWJyYXJ5KCJmb3JlY2FzdCIpDQp9DQojIyANCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSwgICAgICAgDQogICAgICAgICAgICAgICAgICAgICAgd2FybmluZyA9IEZBTFNFLCAgIA0KICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IFRSVUUsICAgDQogICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZSA9IEZBTFNFLA0KICAgICAgICAgICAgICAgICAgICAgIGNvbW1lbnQgPSBOQSkNCmBgYA0KIyBEYXRhIFByZXBhcmF0aW9uDQoNClRvIGNyZWF0ZSB0aGUgZGF0YSBzZXQgdXNlZCBmb3IgdGhpcyBhbmFseXNpcywgZm91ciBkYXRhIHNldHMgd2VyZSBpbXBvcnRlZCBhbmQgbWFuaXB1bGF0ZWQuIE9uZSBkYXRhc2V0IGluY2x1ZGVkIGluY29tZSwgb25lIGxpZmUgZXhwZWN0YW5jeSwgb25lIHBvcHVsYXRpb24gc2l6ZSwgYW5kIGEgZmluYWwgZGF0YXNldCB3aXRoIHJlZ2lvbi4gQWxsIGRhdGEgc2V0cyB3ZXJlIGNvbWJpbmVkIGluIG9yZGVyIHRvIGNyZWF0ZSBhIGZpbmFsIGRhdGEgc2V0IHdpdGggdGhlIGZvbGxvd2luZyB2YXJpYWJsZXM6IA0KDQoqICoqQ291bnRyeSoqDQoqICoqSW5jb21lKioNCiogKipZZWFyKioNCiogKipMaWZlIEV4cGVjdGFuY3kqKg0KKiAqKlJlZ2lvbioqDQoqICoqUG9wdWxhdGlvbiBTaXplKioNCg0KVGhpcyBmaW5hbCBkYXRhIHNldCB3aWxsIGJlIGV2YWx1YXRlZCBpbiB0aGUgZm9sbG93aW5nIHNlY3Rpb25zLiBQbGVhc2UgcmVmZXIgdG8gdGhlIGZvbGxvd2luZyBjb2RlIHRoYXQgd2FzIHVzZWQgaW4gb3JkZXIgdG8gY3JlYXRlIHRoaXMgZGF0YXNldC4gDQoNCmBgYHtyfQ0KDQppbmNvbWUgPC0gcmVhZC5jc3YoZmlsZT0iaHR0cHM6Ly9pc2FyZW5uLmdpdGh1Yi5pby9pcmVubmVuYmVyZy9XZWVrNS9pbmNvbWVfcGVyX3BlcnNvbi5jc3YiKQ0KbGlmZSA8LSByZWFkLmNzdihmaWxlPSJodHRwczovL2lzYXJlbm4uZ2l0aHViLmlvL2lyZW5uZW5iZXJnL1dlZWs1L2xpZmVfZXhwZWN0YW5jeV95ZWFycy5jc3YiKQ0KcG9wdWxhdGlvbiA8LSByZWFkLmNzdihmaWxlPSJodHRwczovL2lzYXJlbm4uZ2l0aHViLmlvL2lyZW5uZW5iZXJnL1dlZWs1L3BvcHVsYXRpb25fdG90YWwuY3N2IikNCnJlZ2lvbiA8LSByZWFkLmNzdigoZmlsZT0iaHR0cHM6Ly9pc2FyZW5uLmdpdGh1Yi5pby9pcmVubmVuYmVyZy9XZWVrNS9jb3VudHJpZXNfdG90YWwuY3N2IikpDQoNCiMjcmVhZGluZyBpbiBmaWxlcyBmcm9tIGdpdGh1Yg0KDQojI3Jlc2hhcGUgaW5jb21lIHNvIHRoYXQgdGhlcmUgYXJlIHRocmVlIGNvbHVtbnMsIGNvdW50cnkgeWVhciBhbmQgaW5jb21lDQoNCmluY29tZTIgPC0gaW5jb21lICU+JQ0KICBnYXRoZXIoa2V5PSJZZWFyIiwNCiAgICAgICAgIHZhbHVlPSJJbmNvbWUiLA0KICAgICAgICAgLSBnZW8sDQogICAgICAgICBuYS5ybT1UUlVFKQ0KaW5jb21lMyA8LSBpbmNvbWUyICU+JQ0KICBtdXRhdGUoWWVhcj1zdWJzdHIoWWVhciwyLDUpKQ0KDQpuYW1lcyhpbmNvbWUzKVsxXT0nQ291bnRyeScNCg0KIyNyZXNoYXBlIGxpZmUgZXhwZWN0YW5jeSA6IGNvdW50cnksIHllYXIsIGxpZmUgZXhwZWN0YW5jeQ0KDQpsaWZlMiA8LSBsaWZlICU+JQ0KICBnYXRoZXIoa2V5PSJZZWFyIiwNCiAgICAgICAgIHZhbHVlPSJMaWZlRXhwIiwNCiAgICAgICAgIC0gZ2VvLA0KICAgICAgICAgbmEucm09VFJVRSkNCmxpZmUzIDwtIGxpZmUyICU+JQ0KICBtdXRhdGUoWWVhcj1zdWJzdHIoWWVhciwyLDUpKQ0KDQpuYW1lcyhsaWZlMylbMV09J0NvdW50cnknDQoNCiMjcmVzaGFwaW5nIHBvcHVsYXRpb24gaW4gdGhlIHNhbWUgd2F5LiANCg0KcG9wMiA8LSBwb3B1bGF0aW9uICU+JQ0KICBnYXRoZXIoa2V5PSJZZWFyIiwNCiAgICAgICAgIHZhbHVlPSJQb3B1bGF0aW9uIiwNCiAgICAgICAgIC0gZ2VvLA0KICAgICAgICAgbmEucm09VFJVRSkNCnBvcDMgPC0gcG9wMiAlPiUNCiAgbXV0YXRlKFllYXI9c3Vic3RyKFllYXIsMiw1KSkNCg0KbmFtZXMocG9wMylbMV09J0NvdW50cnknDQoNCiMjTWVyZ2Uvam9pbiB0aGUgYWJvdmUgbGlmZSBhbmQgaW5jb21lIHNldHMgdG8gY3JlYXRlIG9uZSBuZXcgZGF0YXNldCAnTGlmZUV4cEluY29tJyB3aXRoIHZhcmlhYmxlcyBjb3VudHJ5LHllYXIsbGlmZWV4cCBhbmQgaW5jb21lDQoNCkxpZmVFeHBJbmNvbSA8LSBtZXJnZShpbmNvbWUzLCBsaWZlMywgYnk9YygiWWVhciIsIkNvdW50cnkiKSkNCg0KIyMgTWVyZ2UgdGhlIGFib3ZlIGRhdGFzZXQgd2l0aCB0aGUgcmVnaW9uIGRhdGFzZXQsIHNvIHRoYXQgdGhlIHJlc3VsdGluZyBkYXRhc2V0IGhhcyBpbmNvbWUsIGxpZmVleHAsIHBvcHVsYXRpb24gc2l6ZSBhbmQgY291bnRyeSByZWdpb24NCg0KbmFtZXMocmVnaW9uKVsxXT0nQ291bnRyeScNCnJlZ2lvbjIgPC0gc3Vic2V0KHJlZ2lvbiwgc2VsZWN0PS1jKGFscGhhLjIsIGFscGhhLjMsIGNvdW50cnkuY29kZSwgaXNvXzMxNjYuMiwgc3ViLnJlZ2lvbiwgaW50ZXJtZWRpYXRlLnJlZ2lvbiwgcmVnaW9uLmNvZGUsIHN1Yi5yZWdpb24uY29kZSwgaW50ZXJtZWRpYXRlLnJlZ2lvbi5jb2RlKSkNCg0KTGlmZUV4cEluY29tMiA8LSBtZXJnZShMaWZlRXhwSW5jb20sIHJlZ2lvbjIsIGJ5PSJDb3VudHJ5IikNCg0KIyNNZXJnZSB0aGUgYWJvdmUgZGF0YXNldCB3aXRoIHBvcHVsYXRpb24gc28gdGhhdCB0aGVyZSBpcyBpbmNvbWUsIGxpZmVleHAsIHBvcHVsYXRpb24gc2l6ZSBjb3VudHJ5IHJlZ2lvbiBhbmQgcG9wdWxhdGlvbiBzaXplDQoNCkxpZmVFeHBJbmNvbTMgPC0gbWVyZ2UoTGlmZUV4cEluY29tMiwgcG9wMywgYnk9YygiWWVhciIsIkNvdW50cnkiKSkNCg0Kd3JpdGUuY3N2KExpZmVFeHBJbmNvbTMsICJMaWZlRXhwSW5jb21GaW5hbC5jc3YiKQ0KDQpgYGANCg0KIyBEYXRhIFNldCBEZXNjcmlwdGlvbg0KDQpUaGUgZmluYWwgZGF0YSBzZXQgaGFzIDM3LDU5MCBvYnNlcnZhdGlvbnMgYW5kIDYgdmFyaWFibGVzLiBUaGUgZGF0YSBzZXRzIHdlcmUgcmV0cmlldmVkIGZyb20gdGhlIGNvdXJzZSBwcm9qZWN0IGRhdGEgcmVwb3NpdG9yeSB1bmRlciB0aGUgV29ybGQgTGlmZSBFeHBlY3RhbmN5IGRhdGEgc2VjdGlvbi4gVGhlIGRhdGEgd2FzIGNvbGxlY3RlZCBmcm9tIGEgcHVibGljIGRvbWFpbi4gDQoNCiMgRGF0YSBGb3IgWWVhciAyMDAwIGFuZCAyMDE1DQoNCkluIG9yZGVyIHRvIHByb2NlZWQgd2l0aCB0aGUgZGF0YSBzZXQsIHR3byBkYXRhc2V0cyB3ZXJlIGNyZWF0ZWQgZnJvbSB0aGUgZm9sbG93aW5nIHllYXJzOiAyMDAwIGFuZCAyMDE1LiBUaGUgZGF0YSB3YXMgc3Vic2V0IHVzaW5nIHRoZSBiZWxvdyBjb2RlLiANCg0KYGBge3J9DQoNCmQyMDAwZGF0YSA8LSBMaWZlRXhwSW5jb20zICU+JQ0KICBmaWx0ZXIoWWVhcj09JzIwMDAnKQ0KDQpkMjAxNWRhdGEgPC0gTGlmZUV4cEluY29tMyAlPiUNCiAgZmlsdGVyKFllYXI9PScyMDE1JykNCg0KYGBgDQoNCiMgVXNhZ2Ugb2YgZ2dwbG90IFNjYXR0ZXJwbG90DQoNCkEgc2NhdHRlciBwbG90IG9mIEluY29tZSBhbmQgTGlmZSBFeHBlY3RhbmN5IHdhcyBjcmVhdGVkIGZvciB0aGUgeWVhciAyMDAwLiANCg0KVGhlIGJlbG93IGRhdGEgcGxvdCBzaG93cyB0aGF0IGxpZmUgZXhwZWN0YW5jeSBpcyB2ZXJ5IGxvdyB0aGUgY2xvc2UgdGhlIGluY29tZSBnZXRzIHRvIHplcm8uIEFzIGluY29tZSBpbmNyZWFzZXMsIGFzIGRvZXMgbGlmZSBleHBlY3RhbmN5LiBMaWZlIGV4cGVjdGFuY3kgaW5jcmVhc2VzIHZlcnkgc2hhcnBseSBmcm9tIDAgdG8gfjE1MDAsIHdoZXJlIGFmdGVyd2FyZHMgaXQgc3RhYmlsaXplcyBhcyBpbmNvbWUgaW5jcmVhc2VzLiANCmBgYHtyLCBmaWcuYWxpZ249J2NlbnRlcid9DQpkMjAwMC5pbmNvbWUgPC0gZDIwMDBkYXRhJEluY29tZQ0KZDIwMDAubGlmZWV4cCA8LSBkMjAwMGRhdGEkTGlmZUV4cA0KZDIwMDAuY291bnRyeSA8LSBkMjAwMGRhdGEkQ291bnRyeQ0KZDIwMDAucmVnaW9uIDwtIGQyMDAwZGF0YSRyZWdpb24NCmQyMDAwLnBvcCA8LSBkMjAwMGRhdGEkUG9wdWxhdGlvbg0KDQpnZ3Bsb3QoZGF0YSA9IGQyMDAwZGF0YSwgbWFwcGluZyA9IGFlcyh4ID0gZDIwMDAuaW5jb21lLCB5ID0gZDIwMDAubGlmZWV4cCkpICsNCiAgZ2VvbV9wb2ludCgpKw0KICBsYWJzKA0KICAgICAgICAgICAgICAgICB4ID0gIkluY29tZSIsDQogICAgICAgICAgICAgICAgIHkgPSAiTGlmZSBFeHBlY3RhbmN5IiwNCiAgICAgICAgICAgICAgICAgdGl0bGUgPSAiQXNzb2NpYXRpb24gYmV0d2VlbiBJbmNvbWUgYW5kIExpZmUgRXhwZWN0YW5jeSIsDQogICAgICAgICAgICAgICAgIHN1YnRpdGxlID0gIkRhdGEgZm9yIHRoZSBZZWFyIDIwMDAiLA0KICAgICAgICAgICAgICAgICBjYXB0aW9uID0gcGFzdGUoIkNyZWF0ZWQgb24iLCBTeXMuRGF0ZSgpKSkgKw0KICAgICAgICAgICAgIHRoZW1lX2dyYXkoKSANCmBgYA0KDQojIE1hbmlwdWxhdGluZyB0aGUgZ2dwbG90IHRvIEluY2x1ZGUgdGhlIFRoaXJkIE51bWVyaWMgVmFyaWFibGUNCg0KTm93LCB0aGUgcG9pbnQgc2l6ZSB3aWxsIGJlIG1hbmlwdWxhdGVkIHRvIGRpc3BsYXkgdGhlIHBvcHVsYXRpb24gc2l6ZSBmb3IgdGhlIHNhbWUgeWVhci4NCg0KVGhpcyBkYXRhc2V0IG5vdyBzaG93cyBiaWdnZXIgcG9pbnRzIGFzIGJlaW5nIGhpZ2hlciBwb3B1bGF0aW9ucy4gSXQgaXMgc2VlbiB0aGF0IGhpZ2hlciBwb3B1bGF0aW9ucyB0ZW5kIHRvIGJlIGxvd2VyIG9uIHRoZSBzcGVjdHJ1bSBpbiB0ZXJtcyBvZiBpbmNvbWUuIFRoZSB2ZXJ5IGhpZ2ggaW5jb21lIGFyZWFzIHNob3cgcG9pbnRzIHRoYXQgaGF2ZSBhIHNtYWxsZXIgc2l6ZSwgYW5kIHRoZXJlZm9yZSBzbWFsbGVyIHBvcHVsYXRpb24uIA0KDQpgYGB7ciwgZmlnLmFsaWduPSdjZW50ZXInfQ0KDQpnZ3Bsb3QoZGF0YSA9IGQyMDAwZGF0YSwgbWFwcGluZyA9IGFlcyh4ID0gZDIwMDAuaW5jb21lLCB5ID0gZDIwMDAubGlmZWV4cCwgc2l6ZT1kMjAwMC5wb3ApKSArDQogIGdlb21fcG9pbnQoKSsNCiAgbGFicygNCiAgICAgICAgICAgICAgICAgeCA9ICJJbmNvbWUiLA0KICAgICAgICAgICAgICAgICB5ID0gIkxpZmUgRXhwZWN0YW5jeSIsDQogICAgICAgICAgICAgICAgIHNpemU9IlBvcHVsYXRpb24gU2l6ZSIsDQogICAgICAgICAgICAgICAgIHRpdGxlID0gIkFzc29jaWF0aW9uIGJldHdlZW4gSW5jb21lIGFuZCBMaWZlIEV4cGVjdGFuY3kiLA0KICAgICAgICAgICAgICAgICBzdWJ0aXRsZSA9ICJEYXRhIGZvciB0aGUgWWVhciAyMDAwIiwNCiAgICAgICAgICAgICAgICAgY2FwdGlvbiA9IHBhc3RlKCJDcmVhdGVkIG9uIiwgU3lzLkRhdGUoKSkpICsNCiAgICAgICAgICAgICB0aGVtZV9ncmF5KCkgDQoNCmBgYA0KDQojIE1hbmlwdWxhdGluZyB0aGUgZ2dwbG90IHRvIEluY2x1ZGUgdGhlIENhdGVnb3JpY2FsIFJlZ2lvbiBWYXJpYWJsZQ0KDQpOb3csIHRoZSBwb2ludCBjb2xvciB3aWxsIGJlIG1hbmlwdWxhdGVkIHRvIHNob3cgdGhlIDUgZGlmZmVyZW50IHJlZ2lvbiBjYXRlZ29yaWVzIGZvciB0aGUgc2FtZSB5ZWFyLiBUaGUgY2F0ZWdvcmllcyBhcmUgYXMgZm9sbG93czogDQoNCiogKipBZnJpY2EqKg0KKiAqKkFtZXJpY2FzKioNCiogKipBc2lhKioNCiogKipFdXJvcGUqKg0KKiAqKk9jZWFuaWEqKiANCg0KVGhpcyBmaW5hbCBzY2F0dGVyIHBsb3Qgc2hvd3MgdXMgc29tZSBkaXN0aW5jdCBzZWN0aW9ucyBmb3Igc2VsZWN0IHJlZ2lvbnMuIFRoZSBsb3dlciByZWdpb24sIG9yIEFmcmljYSwgdGVuZHMgdG8gYmUgbG9jYWxpemVkIG5lYXIgdGhlIGxvd2VyIGxpZmUgZXhwZWN0YW5jeSBhbmQgbG93ZXIgaW5jb21lLiBUaGUgQXNpYSByZWdpb24gc3BhbnMgdGhlIGxhcmdlc3QgaW5jb21lIHJhbmdlLCBmcm9tIGJlaW5nIGxvY2FsaXplZCBhYm92ZSB0aGUgQWZyaWNhIGNsdXN0ZXIsIHRvIGFsbCB0aGUgd2F5IHRvIHRoZSByaWdodCAob3IgdGhlIGhpZ2hlc3QgaW5jb21lIGdyb3VwKS4gV2l0aGluIHRoZSBBc2lhIGdyb3VwLCBPY2VhbmlhLCBBbWVyaWNhcyBhbmQgRXVyb3BlIHJlc2lkZS4gTm90IGFsbCByZWdpb25zIGFyZSBpc29sYXRlZCB0byBvbmUgYXJlYSBvZiB0aGUgc2NhdHRlciBwbG90LiBUaGVyZSBhcmUgY2VydGFpbiB0cmVuZHMgZm9yIGFyZWFzIGluIHdoaWNoIHRoZSByZWdpb25zIHJlc2lkZSwgYnV0IHRoZXJlIGFyZSBzb21lIHBvaW50cyB0aGF0IGV4Y2VlZCB0aGF0IGFyZWEuIEZvciBleGFtcGxlLCB0aGVyZSBhcmUgYSBmZXcgQWZyaWNhIHJlZ2lvbiBwb2ludHMgdGhhdCBhcmUgYW1vbmcgdGhlIEFtZXJpY2FzL0V1cm9wZS9Bc2lhIHBvaW50cy4gDQoNCkl0IGlzIGltcG9ydGFudCB0byBub3RlIHRoYXQgdGhlIGZyZXF1ZW5jeSBmb3IgdGhlIE9jZWFuaWEgcmVnaW9uIGlzIG11Y2ggbG93ZXIgdGhhbiB0aGUgb3RoZXIgcmVnaW9ucy4gDQoNCmBgYHtyLCBmaWcuYWxpZ249J2NlbnRlcid9DQoNCmdncGxvdChkYXRhID0gZDIwMDBkYXRhLCBtYXBwaW5nID0gYWVzKHggPSBkMjAwMC5pbmNvbWUsIHkgPSBkMjAwMC5saWZlZXhwLCBzaXplPWQyMDAwLnBvcCwgY29sb3I9ZDIwMDAucmVnaW9uKSkgKw0KICBnZW9tX3BvaW50KCkrDQogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXM9YygiI0ZGRDcwMCIsICIjRUE1Rjk0IiwiIzAwMDBGRiIsIiM4NEZGQTkiLCIjRkY4RjAwIikpICsNCiAgbGFicygNCiAgICAgICAgICAgICAgICAgeCA9ICJJbmNvbWUiLA0KICAgICAgICAgICAgICAgICB5ID0gIkxpZmUgRXhwZWN0YW5jeSIsDQogICAgICAgICAgICAgICAgIHNpemU9IlBvcHVsYXRpb24gU2l6ZSIsDQogICAgICAgICAgICAgICAgIGNvbG9yPSJSZWdpb24iLA0KICAgICAgICAgICAgICAgICB0aXRsZSA9ICJBc3NvY2lhdGlvbiBiZXR3ZWVuIEluY29tZSBhbmQgTGlmZSBFeHBlY3RhbmN5IiwNCiAgICAgICAgICAgICAgICAgc3VidGl0bGUgPSAiRGF0YSBmb3IgdGhlIFllYXIgMjAwMCIsDQogICAgICAgICAgICAgICAgIGNhcHRpb24gPSBwYXN0ZSgiQ3JlYXRlZCBvbiIsIFN5cy5EYXRlKCkpKSArDQogICAgICAgICAgICAgdGhlbWVfZ3JheSgpIA0KDQpgYGANCg0KIyBJbnRlcmFjdGl2ZSBQbG90IGZvciBZZWFyIDIwMTUNCg0KQW4gaW50ZXJhY3RpdmUgcGxvdCB3YXMgY3JlYXRlZCBmb3IgdGhlIDIwMTUgZGF0YXNldC4gVGhlIGludGVyYWN0aXZlIHNjYXR0ZXIgcGxvdCB3YXMgbWFkZSB0byBkaXNwbGF5IHRoZSBhc3NvY2lhdGlvbiBiZXR3ZWVuIGxpZmUgZXhwZWN0YW5jeSBhbmQgaW5jb21lLiANCg0KU2luY2UgcG9wdWxhdGlvbiBzaXplIHdhcyBzbyBsYXJnZSwgaXQgd2FzIHNpemVkIGJ5IGRpdmlkaW5nIHRoZSBwb3B1bGF0aW9uIGJ5OiAqKn4oMipsb2coZGF0YS5wb3ApLTExKV4yLioqIC4NCg0KYGBge3IsIGZpZy5hbGlnbj0nY2VudGVyJywgZmlnLndpZHRoPTUsIGZpZy5oZWlnaHQ9Nn0NCmQyMDE1LmluY29tZSA8LSBkMjAxNWRhdGEkSW5jb21lDQpkMjAxNS5saWZlZXhwIDwtIGQyMDE1ZGF0YSRMaWZlRXhwDQpkMjAxNS5jb3VudHJ5IDwtIGQyMDE1ZGF0YSRDb3VudHJ5DQpkMjAxNS5yZWdpb24gPC0gZDIwMTVkYXRhJHJlZ2lvbg0KZDIwMTUucG9wIDwtIGQyMDE1ZGF0YSRQb3B1bGF0aW9uDQpkMjAxNS5wb3AyIDwtIGQyMDE1LnBvcC8xMDAwMDAwMA0KcGFsIDwtIGMoIiNmZmJlMGIiLCAiI2ZiNTYwNyIsICIjZmYwMDZlIiwiIzgzMzhlYyIsIiMzYTg2ZmYiKQ0KDQpwbG90X2x5KA0KICAgIGRhdGEgPSBkMjAxNWRhdGEsDQogICAgeCA9IH5kMjAxNS5pbmNvbWUsICAjIEhvcml6b250YWwgYXhpcyANCiAgICB5ID0gfmQyMDE1LmxpZmVleHAsICAgIyBWZXJ0aWNhbCBheGlzIA0KICAgIGNvbG9yID0gfmZhY3RvcihkMjAxNS5yZWdpb24pLCAgIyBtdXN0IGJlIGEgbnVtZXJpYyBmYWN0b3INCiAgICBjb2xvcnM9cGFsLA0KICAgIHRleHQgPSB+cGFzdGUoIlBvcHVsYXRpb24gU2l6ZTogIiwgZDIwMTUucG9wLA0KICAgICAgICAgICAgICAgICAgICI8YnI+UmVnaW9uOiIsIGQyMDE1LnJlZ2lvbiwNCiAgICAgICAgICAgICAgICAgICAiPGJyPkNvdW50cnk6IiwgZDIwMTUuY291bnRyeSksIA0KICAgICAjIFNob3cgdGhlIHNwZWNpZXMgaW4gdGhlIGhvdmVyIHRleHQNCiAgICAgIyMgdXNpbmcgdGhlIGZvbGxvd2luZyBob3ZlcnRlbXBsYXRlKCkgdG8gYWRkIHRoZSBpbmZvcm1hdGlvbiBvZiB0aGUNCiAgICAgIyMgVHdvIG51bWVyaWNhbCB2YXJpYWJsZXMgdG8gdGhlIGhvdmVyIHRleHQuDQogICAgICMjIyBVc2UgdGhlIGZvbGxvd2luZyBob3ZlciB0ZW1wbGF0ZSB0byBkaXNwbGF5IG1vcmUgaW5mb3JtYXRpb24NCiAgICAgaG92ZXJ0ZW1wbGF0ZSA9IHBhc3RlKCc8aT48Yj5MaWZlIEV4cGVjdGFuY3k8Yj48L2k+OiAle3l9JywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICc8YnI+PGI+SW5jb21lPC9iPjogICV7eH0nLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgJzxicj48Yj4le3RleHR9PC9iPicpLA0KICAgICBhbHBoYSAgPSAwLjYsDQogICAgIG1hcmtlciA9IGxpc3Qoc2l6ZSA9IH5+KDIqbG9nKGQyMDE1LnBvcCktMTEpXjIsIHNpemVyZWYgPSAuMDUsIHNpemVtb2RlID0gJ2FyZWEnICksDQogICAgIHR5cGUgPSAic2NhdHRlciIsDQogICAgIG1vZGUgPSAibWFya2VycyIsDQogICAgIHNpemUubW9kZT0nYXJlYScsDQogICAgICMjIGdyYXBoaWMgc2l6ZQ0KICAgICB3aWR0aCA9IDcwMCwNCiAgICAgaGVpZ2h0ID0gMzUwDQogICApICU+JQ0KICAgIGxheW91dCggIA0KICAgICAgIyMjIFRpdGxlIA0KICAgICAgdGl0bGUgPWxpc3QodGV4dCA9ICJJbmNvbWUgdnMgTGlmZSBFeHBlY3RhbmN5IGZvciB0aGUgWWVhciAyMDE1IiwgDQogICAgICAgICAgICAgICAgICBmb250ID0gbGlzdChmYW1pbHkgPSAiVGltZXMgTmV3IFJvbWFuIiwgICMgSFRNTCBmb250IGZhbWlseSAgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpemUgPSAxOCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvciA9ICIjZmYwMDZlIikpLCANCiAgICAgICMjIyBsZWdlbmQNCiAgICAgIGxlZ2VuZCA9IGxpc3QodGl0bGUgPSBsaXN0KHRleHQgPSAnUmVnaW9uJywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvbnQgPSBsaXN0KGZhbWlseSA9ICJUaW1lcyBOZXcgUm9tYW4iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaXplID0gMTQsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb3IgPSAiYmxhY2siKSksDQogICAgICAgICAgICAgICAgICAgIGJnY29sb3IgPSAiI2Y3ZjdmNyIsDQogICAgICAgICAgICAgICAgICAgIGJvcmRlcmNvbG9yID0gImJsYWNrIiwNCiAgICAgICAgICAgICAgICAgICAgZ3JvdXBjbGljayA9ICJ0b2dnbGVncm91cCIsICAjIG9uZSBvZiAgInRvZ2dsZWl0ZW0iIEFORCAidG9nZ2xlZ3JvdXAiLg0KICAgICAgICAgICAgICAgICAgICBvcmllbnRhdGlvbiA9ICJ2IiAgIyBTZXRzIHRoZSBvcmllbnRhdGlvbiBvZiB0aGUgbGVnZW5kLg0KICAgICAgICAgICAgICAgICAgICApLA0KICAgICAgIyMgQmFja2dyb3VuZHMNCiAgICAgIHBsb3RfYmdjb2xvciA9JyNmN2Y3ZjcnLCANCiAgICAgICMjIEF4ZXMgbGFiZWxzDQogICAgICAgICAgICAgeGF4aXMgPSBsaXN0KCANCiAgICAgICAgICAgICAgICAgICAgdGl0bGU9bGlzdCh0ZXh0ID0gJ0luY29tZScsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9udCA9IGxpc3QoZmFtaWx5ID0gJ1RpbWVzIE5ldyBSb21hbicpKSwNCiAgICAgICAgICAgICAgICAgICAgemVyb2xpbmVjb2xvciA9ICdncmF5JywgDQogICAgICAgICAgICAgICAgICAgIHplcm9saW5ld2lkdGggPSAyLCANCiAgICAgICAgICAgICAgICAgICAgZ3JpZGNvbG9yID0gJ3doaXRlJyksIA0KICAgICAgICAgICAgeWF4aXMgPSBsaXN0KCANCiAgICAgICAgICAgICAgICAgICAgdGl0bGU9bGlzdCh0ZXh0ID0gJ0xpZmUgRXhwZWN0YW5jeScsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9udCA9IGxpc3QoZmFtaWx5ID0gJ1RpbWVzIE5ldyBSb21hbicpKSwNCiAgICAgICAgICAgICAgICAgICAgemVyb2xpbmVjb2xvciA9ICdwdXJwbGUnLCANCiAgICAgICAgICAgICAgICAgICAgemVyb2xpbmV3aWR0aCA9IDIsIA0KICAgICAgICAgICAgICAgICAgICBncmlkY29sb3IgPSAnd2hpdGUnKSwNCiAgICAgICAjIyBhbm5vdGF0aW9ucw0KICAgICAgIGFubm90YXRpb25zID0gbGlzdCggIA0KICAgICAgICAgICAgICAgICAgICAgeCA9IDAuNywgICAjIGJldHdlZW4gMCBhbmQgMS4gMCA9IGxlZnQsIDEgPSByaWdodA0KICAgICAgICAgICAgICAgICAgICAgeSA9IDEuNSwgICAjIGJldHdlZW4gMCBhbmQgMSwgMCA9IGJvdHRvbSwgMSA9IHRvcA0KICAgICAgICAgICAgICAgICAgZm9udCA9IGxpc3Qoc2l6ZSA9IDEyLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb3IgPSAiI2ZmMDA2ZSIpLCAgIA0KICAgICAgICAgICAgICAgICAgdGV4dCA9ICJUaGUgcG9pbnQgc2l6ZSBpcyBwcm9wb3J0aW9uYWwgdG8gcG9wdWxhdGlvbiBzaXplLiIsICAgDQogICAgICAgICAgICAgICAgICB4cmVmID0gInBhcGVyIiwgICMgImNvbnRhaW5lciIgc3BhbnMgdGhlIGVudGlyZSBgd2lkdGhgIG9mIHRoZSANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyAgbG90LiAicGFwZXIiIHJlZmVycyB0byB0aGUgd2lkdGggb2YgdGhlIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjICBwbG90dGluZyBhcmVhIG9ubHkuIHlyZWYgPSAicGFwZXIiLCAgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgIHNhbWUgYXMgeHJlZi4NCiAgICAgICAgICAgICAgIHhhbmNob3IgPSAiY2VudGVyIiwgIyAgaG9yaXpvbnRhbCBhbGlnbm1lbnQgd2l0aCByZXNwZWN0IHRvIGl0cyB4IHBvc2l0aW9uDQogICAgICAgICAgICAgICB5YW5jaG9yID0gImJvdHRvbSIsICMgIHNpbWlsYXIgdG8geGFuY2hvciAgDQogICAgICAgICAgICAgc2hvd2Fycm93ID0gRkFMU0UpDQogICAgKQ0KYGBgDQoNCiMgQW5pbWF0ZWQgUGxvdA0KDQpUaGlzIGFuaW1hdGVkIHBsb3QgYWlkcyBpbiBsb29raW5nIGF0IHRoZSB0cmVuZHMgb3ZlciB0aW1lIGZvciB0aGUgYXNzb2NpYXRpb24gYmV0d2VlbiBpbmNvbWUgYW5kIGxpZmUgZXhwZWN0YW5jeSBmb3IgdGhlIGVudGlyZXR5IG9mIHRoZSBkYXRhc2V0LiANCg0KYGBge3J9DQoNCmRhdGEuaW5jb21lIDwtIExpZmVFeHBJbmNvbTMkSW5jb21lDQpkYXRhLmxpZmVleHAgPC0gTGlmZUV4cEluY29tMyRMaWZlRXhwDQpkYXRhLmNvdW50cnkgPC0gTGlmZUV4cEluY29tMyRDb3VudHJ5DQpkYXRhLnJlZ2lvbiA8LSBMaWZlRXhwSW5jb20zJHJlZ2lvbg0KZGF0YS5wb3AgPC0gTGlmZUV4cEluY29tMyRQb3B1bGF0aW9uDQpkYXRhLnllYXIgPC0gTGlmZUV4cEluY29tMyRZZWFyDQpwYWwuSUJNIDwtIGMoIiNmZmJlMGIiLCAiI2ZiNTYwNyIsICIjZmYwMDZlIiwiIzgzMzhlYyIsIiMzYTg2ZmYiKQ0KcGFsLklCTSA8LSBzZXROYW1lcyhwYWwuSUJNLCBjKCJBc2lhIiwgIkV1cm9wZSIsICJBZnJpY2EiLCAiQW1lcmljYXMiLCAiT2NlYW5pYSIpKQ0KDQpkZiA8LSBMaWZlRXhwSW5jb20zIA0KZmlnIDwtIGRmICU+JQ0KICBwbG90X2x5KA0KICAgIHggPSB+ZGF0YS5pbmNvbWUsIA0KICAgIHkgPSB+ZGF0YS5saWZlZXhwLCANCiAgICBzaXplID0gfigyKmxvZyhkYXRhLnBvcCktMTEpXjIsDQogICAgY29sb3IgPSB+ZGF0YS5yZWdpb24sIA0KICAgIGNvbG9ycyA9IHBhbC5JQk0sICAgIyBjdXN0b20gY29sb3JzDQogICAgI21hcmtlciA9IGxpc3Qoc2l6ZSA9IH4obG9nKHBvcCktMTApLCAgc2l6ZW1vZGUgPSAnYXJlYScpLA0KICAgIGZyYW1lID0gfmRhdGEueWVhciwgICAgICAjIHRoZSB0aW1lIHZhcmlhYmxlIHRvDQogICAgIyB0byBkaXNwbGF5IGluIHRoZSBob3Zlcg0KICAgIHRleHQgPSB+cGFzdGUoIkNvdW50cnk6IiwgZGF0YS5jb3VudHJ5LA0KICAgICAgICAgICAgICAgICAgIjxicj5Db250aW5lbnQ6IiwgZGF0YS5yZWdpb24sDQogICAgICAgICAgICAgICAgICAiPGJyPlllYXI6IiwgZGF0YS55ZWFyLA0KICAgICAgICAgICAgICAgICAgIjxicj5JbmNvbWU6IiwgZGF0YS5pbmNvbWUsDQogICAgICAgICAgICAgICAgICAiPGJyPkxpZmVFeHA6IiwgZGF0YS5saWZlZXhwLA0KICAgICAgICAgICAgICAgICAgIjxicj5Qb3B1bGF0aW9uOiIsIGRhdGEucG9wKSwNCiAgICBob3ZlcmluZm8gPSAidGV4dCIsDQogICAgdHlwZSA9ICdzY2F0dGVyJywNCiAgICBtb2RlID0gJ21hcmtlcnMnDQogICkgJT4lDQogIGxheW91dCgNCiAgICB0aXRsZT1saXN0KHRleHQ9IkluY29tZSB2cyBMaWZlIEV4cGVjdGFuY3kgZnJvbSAxODAwLTIwMTgiLA0KICAgICAgICAgICAgICAgZm9udD1saXN0KGZhbWlseT0iVGltZSBOZXcgUm9tYW4iLA0KICAgICAgICAgICAgICAgICAgICAgICAgIHNpemU9MTgsDQogICAgICAgICAgICAgICAgICAgICAgICAgY29sb3I9IiNmZjAwNmUiKSksDQogICAgeGF4aXMgPSBsaXN0KCANCiAgICAgICAgICAgICAgICAgICAgdGl0bGU9bGlzdCh0ZXh0ID0gJ0luY29tZScsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9udCA9IGxpc3QoZmFtaWx5ID0gJ1RpbWVzIE5ldyBSb21hbicpKSwNCiAgICAgICAgICAgICAgICAgICAgZ3JpZGNvbG9yID0gJ3doaXRlJyksIA0KICAgICAgICAgICAgeWF4aXMgPSBsaXN0KCANCiAgICAgICAgICAgICAgICAgICAgdGl0bGU9bGlzdCh0ZXh0ID0gJ0xpZmUgRXhwZWN0bmFjeScsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9udCA9IGxpc3QoZmFtaWx5ID0gJ1RpbWVzIE5ldyBSb21hbicpKSwNCiAgICAgICAgICAgICAgICAgICAgZ3JpZGNvbG9yID0gJ3doaXRlJykNCiAgKQ0KZmlnIDwtIGZpZyAlPiUgbGF5b3V0KA0KICAgIHhheGlzID0gbGlzdCgNCiAgICAgIHR5cGUgPSAibG9nIg0KICAgICkNCiAgKQ0KDQpmaWcNCmBgYA0KDQojIEZpbmFsIENvbmx1c2lvbnMgDQoNClRoZSBvcmlnaW5hbCBkYXRhIHNldHMgd2VyZSBtYW5pcHVsYXRlZCB0byBjcmVhdGUgb25lIGxhcmdlIGRhdGFzZXQgd2l0aCB0aGUgZm9sbG93aW5nIHZhcmlhYmxlczogY291bnRyeSwgaW5jb21lLCB5ZWFyLCBsaWZlIGV4cGVjdGFuY3ksIHJlZ2lvbiBhbmQgcG9wdWxhdGlvbiBzaXplLiANCg0KQXMgc2VlbiB3aXRoIHRoZSBhbmltYXRlZCBzY2F0dGVyIHBsb3QgKHByZXZpb3VzIHNlY3Rpb24pLCBpbmNvbWUgYW5kIGxpZmUgZXhwZWN0YW5jeSBpbmNyZWFzZWQgb3ZlciB0aW1lIGZyb20gdGhlIHllYXJzIDE4MDAtMjAxOCAodGhlIGVudGlyZSBzcGFuIG9mIHRoZSBkYXRhIHNldHMpLiBUaGVyZSB3ZXJlIHNldmVyYWwgaW5zdGFuY2VzIGluIHdoaWNoIHRoZXJlIHdlcmUgZHJhc3RpYyBkcm9wcyBpbiB0aGUgbGlmZSBleHBlY3RhbmN5LCBhcm91bmQgdGhlIHRpbWUgb2YgV29ybGQgV2Fycy4gVGhlcmUgaXMgYSByZWxhdGlvbnNoaXAgdGhyb3VnaG91dCB0aW1lIGJldHdlZW4gbGlmZSBleHBlY3RhbmN5IGFuZCBpbmNvbWUuICANCg0KRm9yIHRoZSB0aHJlZSBncmFwaHMgY3JlYXRlZCB3aXRoIHRoZSBkYXRhIGZyb20gMjAwMCwgaXQgaXMgZXZpZGVudCB0aGF0IHRoZXJlIGlzIGEgcmVsYXRpb25zaGlwIGJldHdlZW4gaW5jb21lIGFuZCBsaWZlIGV4cGVjdGFuY3kuIFBvaW50cyBvZiBoaWdoIGluY29tZSBhbmQgbGlmZSBleHBlY3RhbmN5IHdlcmUgYWxsIHNtYWxsZXIgaW4gc2l6ZSwgaW5kaWNhdGluZyBhIGxvd2VyIHBvcHVsYXRpb24sIHdpdGggdGhlIGV4Y2VwdGlvbiBvZiBhIHBvaW50IGZvciB0aGUgQW1lcmljYXMgaW4gdGhlIGZpbmFsIGdyYXBoLiBJdCB3YXMgZm91bmQgdGhhdCB3aGVuIGNoYW5naW5nIHRoZSBjb2xvciBmb3IgcmVnaW9uLCBpdCB3YXMgbW9zdCBldmlkZW50IHRoYXQgdGhlIEFmcmljYSByZWdpb24gd2FzIGRlbnNlbHkgY2xvc2UgYXQgdGhlIGxvd2VyIGluY29tZSBhbmQgbG93ZXIgbGlmZSBleHBlY3RhbmN5IGFyZWEuIFRoZSBvdGhlciBmb3VyIHJlZ2lvbnMtIE9jZWFuaWEsIEV1cm9wZSwgQXNpYSBhbmQgQW1lcmljYXMsIHdlcmUgKGZvciB0aGUgbW9zdCBwYXJ0KSBoaWdoZXIgdGhhbiB0aGUgQWZyaWNhIHJlZ2lvbiBmb3IgbGlmZSBleHBlY3RhbmN5IGFuZCBpbmNvbWUuIFRoZXJlIHdlcmUgc29tZSBBZnJpY2EgcG9pbnRzIG9uIHRoZSBncmFwaCB0aGF0IHdlcmUgYW1vbmcgdGhlIG90aGVyIHJlZ2lvbnMuIFRoZSBBc2lhIHJlZ2lvbiB3YXMgc2Vjb25kIHRvIEFmcmljYSBpbiB0aGF0IHRoZXJlIHNlZW1lZCB0byBiZSBncm91cGluZyBvZiBwb2ludHMgaW4gdGhlIG1pZC1yYW5nZSBvZiB0aGUgZ3JhcGguIA0KDQpUaGUgZ3JhcGggc2hvd2VkIHRoYXQgZnJvbSB0aGUgMCB0byB+MTUwMCBpbmNvbWUgcmFuZ2UsIHRoZXJlIHdhcyBhIHNoYXJwIGluY3JlYXNlIGluIGxpZmUgZXhwZWN0YW5jeS4gRm9sbG93aW5nIH4zMCwwMDAgKGluY29tZSkgdGhlIGxpZmUgZXhwZWN0YW5jeSByZW1haW5zIHN0YWJsZS4gTGlmZSBleHBlY3RhbmN5IHdhcyB0aGUgbG93ZXN0IHdoZW4gaW5jb21lIHdhcyBpbmNyZWRpYmx5IGNsb3NlIHRvIDAsIGFuZCBpbmNyZWFzZWQgZXhwb25lbnRpYWxseSB0aGUgZmFydGhlciBhd2F5IGZyb20gemVybyB1bnRpbCB0aGUgc3RhYmlsaXphdGlvbiBvY2N1cnJlZC4gDQoNCkZvciB0aGUgaW50ZXJhY3RpdmUgcGxvdCBmcm9tIHRoZSB5ZWFyIDIwMTUsIHRoZXJlIGFyZSBzaW1pbGFyIHJlbGF0aW9uc2hpcHMgaW4gdGhlIGdyYXBoLiBOb3RhYmx5LCB0aGUgcG9pbnQgd2l0aCB0aGUgaGlnaGVzdCBpbmNvbWUgY29tZXMgZnJvbSBRYXRhciwgYW5kIHRoZSBsb3dlc3QgaW5jb21lIChhbmQgbGlmZSBleHBlY3RhbmN5KSBjb21lcyBmcm9tIHRoZSBDZW50cmFsIEFmcmljYW4gUmVwdWJsaWMuIFNpbWlsYXJseSB0byB0aGUgMjAwMCB5ZWFyIHNjYXR0ZXIgcGxvdCwgdGhlcmUgaXMgYSBzaGFycCBpbmNyZWFzZSBlYXJsaWVyIGluIHRoZSBwbG90LCBhbmQgdGhlbiBhIGxldmVsaW5nIG91dCwgYXJvdW5kIDIwLDAwMC4gDQoNClRoYW5rIHlvdSBhbmQgZ29vZCBuaWdodCEg